package s63.kong.shop.modules.token;

import com.baomidou.mybatisplus.core.toolkit.AES;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.Base64UrlCodec;
import lombok.extern.slf4j.Slf4j;
import s63.kong.shop.modules.security.LoginUser;
import s63.kong.shop.pojo.User;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j//这里不需要加@Service注解，因为在程序运行的时候在TokenConfig配置文件中已经实例化好了
public class JwtTokenService implements ITokenService {
    @Override
    public Token createToken(LoginUser loginUser) {
        String token = JwtUtils.createToken(loginUser);
        return new Token(token,loginUser.getUser().getNickName());
    }

    @Override
    public boolean removeToken(String token) {
        throw new RuntimeException("方法未实现");
    }

    @Override
    public LoginUser getLoginUser(String token) {
        return JwtUtils.getLoginUser(token);
    }

    private static class JwtUtils {
        private static final String secret = "@!#&ZQ1314$NFenG";//密钥
        private static final String PAYLOAD_KEY = "payload";//负载数据对应的Map键


        public static String createToken(LoginUser loginUser) {
            String rawData = String.join("#",loginUser.getUser().getUserId()+"",
                    loginUser.getRoleKeyList().stream().collect(Collectors.joining(",")),
                    loginUser.getPermsList().stream().collect(Collectors.joining(",")));

            Map<String,Object> payload = new HashMap<>();
            payload.put(PAYLOAD_KEY,AES.encrypt(rawData,secret));

            return Jwts.builder()
                    .setIssuedAt(new Date())//设置 JWT 的签发时间为当前时间
                    .setExpiration(new Date(System.currentTimeMillis() + 15*60*1000))//设置JWT的过期时间为当前时间加15分钟
                    .setClaims(payload)// 设置JWT的负载，也就是要包含在 JWT 中的数据
                    .signWith(SignatureAlgorithm.HS256, Base64UrlCodec.BASE64URL.encode(secret))//用HS256签名算法对JWT进行签名,secret 是用于签名的密钥。
                    .compact();//构建JWT并将其序列化为一个字符串。
        }

        public static LoginUser getLoginUser(String token) {
            Claims body = Jwts.parser()
                    .setSigningKey(Base64UrlCodec.BASE64URL.encode(secret))
                    .parseClaimsJws(token).getBody();

            String rawData = (String) body.get(PAYLOAD_KEY);//取出负载的数据
            String[] decrypt = AES.decrypt(rawData, secret).split("#");

            if (log.isDebugEnabled()){
                log.debug("解密前的数据："+rawData);
                log.debug("解密后的数据："+ Arrays.asList(decrypt));
            }
            Long userId = Long.valueOf(decrypt[0]);
            List<String> roleKeyList = Arrays.asList(decrypt[1].split(","));
            List<String> permsList = Arrays.asList(decrypt[2].split(","));

            User user = new User();
            user.setUserId(userId);
            return new LoginUser(user,roleKeyList,permsList);
        }
    }
}
